package com.hjh.usb.accessory.communication

import android.hardware.usb.UsbAccessory
import android.hardware.usb.UsbManager
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.io.FileInputStream
import java.io.FileOutputStream

class AOAConnectionManager(
    private val usbManager: UsbManager,
    private val scope: CoroutineScope
) {
    private val mutex = Mutex()
    private var currentAccessory: UsbAccessory? = null
    private var inputStream: FileInputStream? = null
    private var outputStream: FileOutputStream? = null

    val sender = AOASender(
        mutex,
        outputStreamProvider = { outputStream },
        scope = scope
    )

    val receiver = AOAReceiver(
        mutex,
        inputStreamProvider = { inputStream },
        scope = scope
    )

    // val communicator = AOACommunicator(
    //     inputStreamProvider = { inputStream },
    //     outputStreamProvider = { outputStream }
    // )

    // val communicator = AOACommunicatorThreadPool(
    //     inputStreamProvider = { inputStream },
    //     outputStreamProvider = { outputStream }
    // )

    val communicator = AOACommunicatorSingleThread(
        inputStreamProvider = { inputStream },
        outputStreamProvider = { outputStream }
    )

    fun connect(accessory: UsbAccessory) {
        scope.launch {
            mutex.withLock {
                actualConnect(accessory)
            }
        }
    }

    private fun actualConnect(accessory: UsbAccessory) {
        UsbFlow.updateConnectionState(ConnectionState.Connecting)
        try {
            val fd = usbManager.openAccessory(accessory)
                ?: throw Exception("无法打开设备")

            inputStream = FileInputStream(fd.fileDescriptor)
            outputStream = FileOutputStream(fd.fileDescriptor)
            currentAccessory = accessory

            communicator.start() // 开始接收 ACK

            UsbFlow.updateConnectionState(ConnectionState.Connected(accessory))
        } catch (e: Exception) {
            e.printStackTrace()
            UsbFlow.updateConnectionState(ConnectionState.Error("连接失败: ${e.message}"))
            cleanupResources()
        }
    }

    fun disconnect() {
        scope.launch {
            mutex.withLock {
                cleanupResources()
                UsbFlow.updateConnectionState(ConnectionState.Disconnected)
            }
        }
    }

    private fun cleanupResources() {
        try {
            inputStream?.close()
            outputStream?.close()
            communicator.stop()
        } catch (_: Exception) {
        }
        inputStream = null
        outputStream = null
        currentAccessory = null
    }
}
